#include "open_url_file_command.h"
#include "service/backend_service.h"
#include "../database/database_manager.h"
#include "command_executor.h"
#include <QDebug>
#include <QUuid>
#include <QDateTime>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QUrlQuery>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QStandardPaths>
#include <QRegularExpression>
#include <QDesktopServices>

OpenUrlFileCommand::OpenUrlFileCommand(QObject *parent)
    : BaseCommand(parent)
    , m_commitUrl("")
    , m_accessToken("")
    , m_currentDownloadUrl("")
{
}

void OpenUrlFileCommand::setBackendService(BackendService *backendService)
{
    // 如果之前已经设置了 backendService，先断开旧的信号连接
    if (m_backendService) {
        disconnect(m_backendService, &BackendService::openFileCompleted,
                   this, &OpenUrlFileCommand::onOpenFileCompleted);
    }
    
    BaseCommand::setBackendService(backendService);
    
    // 连接文件打开完成信号（用于检测下载失败）
    if (m_backendService) {
        connect(m_backendService, &BackendService::openFileCompleted,
                this, &OpenUrlFileCommand::onOpenFileCompleted);
    }
}

void OpenUrlFileCommand::setNetworkAccessManager(QNetworkAccessManager *networkManager)
{
    // 如果之前已经设置了 networkManager，先断开旧的信号连接
    if (m_networkManager) {
        disconnect(m_networkManager, &QNetworkAccessManager::finished,
                   this, &OpenUrlFileCommand::onNetworkReplyFinished);
    }
    
    BaseCommand::setNetworkAccessManager(networkManager);
    
    // 连接网络请求完成信号
    if (m_networkManager) {
        connect(m_networkManager, &QNetworkAccessManager::finished,
                this, &OpenUrlFileCommand::onNetworkReplyFinished);
    }
}

bool OpenUrlFileCommand::execute(const QJsonObject &jsonObj)
{
    if (!isValid()) {
        qDebug() << "OpenUrlFileCommand: BackendService 或 QNetworkAccessManager 未设置，无法执行命令";
        return false;
    }
    
    // 构建 PARAMS JSON
    QString downloadUrl = jsonObj.value("downloadurl").toString();
    QString commitUrl = jsonObj.value("commiturl").toString();
    QString accessToken = jsonObj.value("accesstoken").toString();
    
    // 保存 commitUrl 和 accessToken，用于文件下载完成后插入 commitfiletourl 指令
    m_commitUrl = commitUrl;
    m_accessToken = accessToken;
    
    // 调用 openFileByURL 打开文件
    qDebug() << QString("收到通过URL打开文件命令，下载URL: %1").arg(downloadUrl);
    
    if (!downloadUrl.isEmpty()) {
        // 保存当前下载URL，用于识别失败
        m_currentDownloadUrl = downloadUrl;
        
        // 请求已成功发送，更新状态为 PROCESSING
        if (m_databaseManager) {
            if (m_databaseManager->updateCommandStatusByDownloadUrl(downloadUrl, "openurlfile", "PROCESSING")) {
                qDebug() << QString("OpenUrlFileCommand: 成功更新命令记录状态为 PROCESSING，下载URL: %1").arg(downloadUrl);
            } else {
                qDebug() << QString("OpenUrlFileCommand: 更新命令记录状态失败，下载URL: %1").arg(downloadUrl);
            }
        }
        
        openFileByURL(downloadUrl, accessToken);
        qDebug() << QString("已调用 OpenUrlFileCommand::openFileByURL，下载URL: %1, accessToken: %2")
                    .arg(downloadUrl, accessToken.isEmpty() ? "空" : "已提供");
        return true;
    } else {
        qDebug() << "下载URL为空，无法打开文件";
        return false;
    }
}

void OpenUrlFileCommand::openFileByURL(const QString &downloadUrl, const QString &accessToken)
{
    qDebug() << "准备通过URL下载并打开文件，URL:" << downloadUrl;
    
    // 验证URL
    if (downloadUrl.isEmpty()) {
        qDebug() << "下载URL为空";
        if (m_backendService) {
            emit m_backendService->openFileCompleted(-1, "下载URL为空");
        }
        return;
    }
    
    // 验证URL格式
    QUrl url(downloadUrl);
    if (!url.isValid()) {
        qDebug() << "无效的URL:" << downloadUrl;
        if (m_backendService) {
            emit m_backendService->openFileCompleted(-1, "无效的URL: " + downloadUrl);
        }
        return;
    }
    
    qDebug() << "开始下载文件，URL:" << downloadUrl;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(url);
    
    // 添加token到请求头
    QString finalAccessToken = getAccessToken(accessToken);
    if (!finalAccessToken.isEmpty()) {
        request.setRawHeader("accessToken", finalAccessToken.toUtf8());
        qDebug() << "已添加accessToken到请求头";
    }
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "发送下载文件请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "downloadFileByURL");
    
    // 保存原始URL
    reply->setProperty("downloadUrl", downloadUrl);
}

void OpenUrlFileCommand::handleDownloadFileByURLResponse(QNetworkReply *reply)
{
    if (!reply) {
        qDebug() << "下载文件响应为空";
        if (m_backendService) {
            emit m_backendService->openFileCompleted(-1, "下载响应为空");
        }
        return;
    }
    
    qDebug() << "处理通过URL下载文件响应，错误:" << reply->error();
    
    if (reply->error() == QNetworkReply::NoError) {
        // 下载成功，保存文件
        QByteArray data = reply->readAll();
        qDebug() << "下载文件成功，数据大小:" << data.size() << "字节";
        
        // 获取临时目录
        const QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
        
        // 构建runtime目录路径（使用临时目录）
        QString runtimeDir = QDir::cleanPath(homeDir + "/.myapps/" + "/runtime");
        
        // 确保runtime目录存在
        if (!QDir().mkpath(runtimeDir)) {
            qDebug() << "创建runtime目录失败:" << runtimeDir;
            if (m_backendService) {
                emit m_backendService->openFileCompleted(-2, "无法创建runtime目录: " + runtimeDir);
            }
            return;
        }
        
        // 从响应头的Content-Disposition中提取文件名
        QString fileName;
        QString contentDisposition = reply->rawHeader("Content-Disposition").constData();
        if (!contentDisposition.isEmpty()) {
            // 解析Content-Disposition: attachment; filename="xxx" 或 filename*=UTF-8''xxx
            QRegularExpression rx("filename\\*?=['\"]?([^'\"\\s;]+)['\"]?");
            QRegularExpressionMatch match = rx.match(contentDisposition);
            if (match.hasMatch()) {
                fileName = match.captured(1);
                // 处理URL编码的文件名（filename*=UTF-8''xxx格式）
                if (fileName.contains("UTF-8''")) {
                    fileName = fileName.mid(fileName.indexOf("UTF-8''") + 7);
                    fileName = QUrl::fromPercentEncoding(fileName.toUtf8());
                }
            } else {
                // 尝试另一种格式：filename="xxx"
                QRegularExpression rx2("filename=\"?([^\";]+)\"?");
                QRegularExpressionMatch match2 = rx2.match(contentDisposition);
                if (match2.hasMatch()) {
                    fileName = match2.captured(1);
                }
            }
        }
        
        // 如果从Content-Disposition中无法获取文件名，尝试从URL中提取
        if (fileName.isEmpty()) {
            QString downloadUrl = reply->property("downloadUrl").toString();
            QUrl url(downloadUrl);
            fileName = QFileInfo(url.path()).fileName();
            // 处理URL参数中的filename（如果有）
            if (fileName.isEmpty() || fileName == "/") {
                QUrlQuery query(url);
                fileName = query.queryItemValue("filename");
            }
        }
        
        // 如果仍然没有文件名，使用时间戳生成
        if (fileName.isEmpty()) {
            fileName = QString("downloaded_file_%1").arg(QDateTime::currentMSecsSinceEpoch());
        }
        
        // 构建目标文件路径
        QString targetPath = QDir::cleanPath(runtimeDir + "/" + fileName);
        
        // 如果文件已存在，添加时间戳后缀
        if (QFile::exists(targetPath)) {
            QFileInfo fileInfo(targetPath);
            QString baseName = fileInfo.baseName();
            QString suffix = fileInfo.completeSuffix();
            QString newFileName = QString("%1_%2.%3")
                                  .arg(baseName)
                                  .arg(QDateTime::currentMSecsSinceEpoch())
                                  .arg(suffix.isEmpty() ? "tmp" : suffix);
            targetPath = QDir::cleanPath(runtimeDir + "/" + newFileName);
        }
        
        qDebug() << "保存文件到:" << targetPath;
        
        // 保存文件
        QFile file(targetPath);
        if (!file.open(QIODevice::WriteOnly)) {
            qDebug() << "无法创建文件:" << targetPath << "错误:" << file.errorString();
            if (m_backendService) {
                emit m_backendService->openFileCompleted(-2, "无法创建文件: " + file.errorString());
            }
            return;
        }
        
        qint64 bytesWritten = file.write(data);
        file.close();
        
        if (bytesWritten != data.size()) {
            qDebug() << "文件写入失败，写入字节数不匹配，期望:" << data.size() << "实际:" << bytesWritten;
            file.remove();
            if (m_backendService) {
                emit m_backendService->openFileCompleted(-3, "文件保存失败，写入字节数不匹配");
            }
            return;
        }
        
        qDebug() << "文件已成功保存到:" << targetPath;
        
        // 处理文件下载完成后的业务逻辑（插入 commitfiletourl 指令、更新状态等）
        QString downloadUrl = reply->property("downloadUrl").toString();
        if (!downloadUrl.isEmpty()) {
            onFileDownloadedByURL(downloadUrl, targetPath);
        }
        
        // 下载完成后，调用openFile打开文件
        openFile(targetPath);
    } else {
        qDebug() << "下载文件失败:" << reply->errorString();
        if (m_backendService) {
            emit m_backendService->openFileCompleted(-1, "下载失败: " + reply->errorString());
        }
    }
}

void OpenUrlFileCommand::openFile(const QString &filePath)
{
    qDebug() << "准备打开文件:" << filePath;
    
    // 检查文件是否存在
    QFileInfo fileInfo(filePath);
    if (!fileInfo.exists()) {
        qDebug() << "文件不存在:" << filePath;
        if (m_backendService) {
            emit m_backendService->openFileCompleted(-1, "文件不存在: " + filePath);
        }
        return;
    }
    
    if (!fileInfo.isFile()) {
        qDebug() << "路径不是文件:" << filePath;
        if (m_backendService) {
            emit m_backendService->openFileCompleted(-2, "路径不是文件: " + filePath);
        }
        return;
    }
    
    // 使用 QDesktopServices 打开文件
    QUrl fileUrl = QUrl::fromLocalFile(filePath);
    bool success = QDesktopServices::openUrl(fileUrl);
    
    if (success) {
        qDebug() << "成功打开文件:" << filePath;
        if (m_backendService) {
            emit m_backendService->openFileCompleted(0, "文件打开成功");
        }
    } else {
        qDebug() << "打开文件失败:" << filePath;
        if (m_backendService) {
            emit m_backendService->openFileCompleted(-3, "无法打开文件，可能没有关联的应用程序");
        }
    }
}

QString OpenUrlFileCommand::getAccessToken(const QString &providedToken)
{
    // 如果传入了 accessToken 参数，使用传入的 token
    if (!providedToken.isEmpty()) {
        return providedToken;
    }
    
    // 否则从 CommandExecutor 获取 accessToken（作为后备）
    QString tokenFromService = CommandExecutor::getAccessToken();
        if (!tokenFromService.isEmpty()) {
            return tokenFromService;
    }
    
    return QString();
}

void OpenUrlFileCommand::onNetworkReplyFinished(QNetworkReply *reply)
{
    if (!reply) {
        return;
    }
    
    QString requestType = reply->property("requestType").toString();
    if (requestType == "downloadFileByURL") {
        handleDownloadFileByURLResponse(reply);
    }
    
    reply->deleteLater();
}

void OpenUrlFileCommand::onFileDownloadedByURL(const QString &downloadUrl, const QString &localFilePath)
{
    qDebug() << "OpenUrlFileCommand: 文件下载完成，下载URL:" << downloadUrl << "本地路径:" << localFilePath;
    
    if (!m_databaseManager) {
        qDebug() << "OpenUrlFileCommand: DatabaseManager 未设置，无法更新命令记录";
        return;
    }
    
    if (downloadUrl.isEmpty() || localFilePath.isEmpty()) {
        qDebug() << "OpenUrlFileCommand: 下载URL或本地文件路径为空";
        return;
    }
    
    // 如果有 COMMIT_URL，插入 commitfiletourl 指令
    bool commitCommandInserted = false;
    if (!m_commitUrl.isEmpty()) {
        KmsCommand commitCommand;
        commitCommand.id = QUuid::createUuid().toString(QUuid::WithoutBraces);
        commitCommand.command = "commitfiletourl";
        
        // 构建 PARAMS JSON：只包含 ACCESS_TOKEN、COMMIT_URL、LOCAL_FILE_PATH
        QJsonObject commitParamsObj;
        if (!m_accessToken.isEmpty()) {
            commitParamsObj["ACCESS_TOKEN"] = m_accessToken;
        }
        commitParamsObj["COMMIT_URL"] = m_commitUrl;
        commitParamsObj["LOCAL_FILE_PATH"] = localFilePath;
        
        QJsonDocument commitJsonDoc(commitParamsObj);
        commitCommand.params = commitJsonDoc.toJson(QJsonDocument::Compact);
        
        QString currentDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        commitCommand.createDate = currentDateTime;
        commitCommand.lastModifyDate = currentDateTime;
        commitCommand.status = "PENDING"; // 待处理
        
        // 插入数据库
        if (m_databaseManager->insertCommand(commitCommand)) {
            commitCommandInserted = true;
            qDebug() << QString("OpenUrlFileCommand: 成功插入 commitfiletourl 指令，ID: %1, COMMIT_URL: %2, LOCAL_FILE_PATH: %3")
                        .arg(commitCommand.id, m_commitUrl, localFilePath);
        } else {
            qDebug() << QString("OpenUrlFileCommand: 插入 commitfiletourl 指令失败，COMMIT_URL: %1").arg(m_commitUrl);
        }
    } else {
        qDebug() << "OpenUrlFileCommand: COMMIT_URL 为空，不插入 commitfiletourl 指令";
    }
    
    // 文件下载成功，更新 openurlfile 命令状态为 COMPLETED
    // 如果有 COMMIT_URL，需要等待 commitfiletourl 指令插入成功后再更新状态
    // 如果没有 COMMIT_URL，直接更新状态
    if (m_commitUrl.isEmpty() || commitCommandInserted) {
        if (m_databaseManager->updateCommandStatusByDownloadUrl(downloadUrl, "openurlfile", "COMPLETED")) {
            qDebug() << QString("OpenUrlFileCommand: 成功更新 openurlfile 命令状态为 COMPLETED，下载URL: %1").arg(downloadUrl);
        } else {
            qDebug() << QString("OpenUrlFileCommand: 更新 openurlfile 命令状态失败，下载URL: %1").arg(downloadUrl);
        }
    }
    
    // 清除当前下载URL
    if (downloadUrl == m_currentDownloadUrl) {
        m_currentDownloadUrl = "";
    }
}

void OpenUrlFileCommand::onOpenFileCompleted(int resultCode, const QString &message)
{
    // 检查是否是当前正在处理的下载失败
    if (m_currentDownloadUrl.isEmpty()) {
        return;  // 不是当前处理的下载，忽略
    }
    
    // 如果 resultCode != 0，说明下载失败
    if (resultCode != 0) {
        qDebug() << QString("OpenUrlFileCommand: 文件下载失败，下载URL: %1, 错误码: %2, 消息: %3")
                    .arg(m_currentDownloadUrl).arg(resultCode).arg(message);
        
        // 更新状态为 FAILED
        if (m_databaseManager) {
            if (m_databaseManager->updateCommandStatusByDownloadUrl(m_currentDownloadUrl, "openurlfile", "FAILED")) {
                qDebug() << QString("OpenUrlFileCommand: 成功更新 openurlfile 命令状态为 FAILED，下载URL: %1").arg(m_currentDownloadUrl);
            } else {
                qDebug() << QString("OpenUrlFileCommand: 更新 openurlfile 命令状态失败，下载URL: %1").arg(m_currentDownloadUrl);
            }
        }
        
        // 清除当前下载URL
        m_currentDownloadUrl = "";
    }
}
